package org.visionlibrary.image.filters.effects;

import javax.media.jai.TiledImage;

import org.visionlibrary.image.acquisition.ImageFactory;
import org.visionlibrary.image.model.AbstractFilter;


public class FishEye extends AbstractFilter {
	@Override
	public TiledImage applyFilter(TiledImage src, TiledImage dest) {
		if (null == src)
			throw new NullPointerException("Source image is null.");

		if (null == dest)
			dest = (new ImageFactory()).createCompatibleImage(src);
		
		int maxX = src.getWidth();
		int maxY = src.getHeight();

		final double dmaxX = (double) maxX / 2;
		final double dmaxY = (double) maxY / 2;
		final double maxR = Math.sqrt(dmaxX * dmaxX + dmaxY * dmaxY);

		for (int x = 0; x < maxX; x++)
			for (int y = 0; y < maxY; y++) {
				for (int ch = 0; ch < src.getNumBands(); ch++) {
					double dx = (double) (x - maxX / 2);// zmniejszyla sie jakos
					// w porownaniu
					double dy = (double) (maxY / 2 - y);// do wersji operujacej
					// na doublach

					double a = Math.atan(dy / dx);

					double r = Math.sqrt(dx * dx + dy * dy);
					double newR = (r * r) / maxR;

					double nx = newR * Math.cos(a);
					double ny = -newR * Math.sin(a);

					// System.out.println("nx=" + nx + " ny=" +ny);

					if (nx < 0.0)
						nx *= (-1.0);
					if (ny < 0.0)
						ny *= (-1.0);

					if (nx > dmaxX)
						nx = dmaxX - 1.0;

					if (ny > dmaxY)
						ny = dmaxY - 1.0;

					int newPixelVal = src.getSample((int) nx, (int) ny, ch);
					dest.setSample(x, y, ch, newPixelVal);
				}
			}

		return dest;
	}
}
